﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.ComponentModel;

namespace Pavilion.DesignerTool
{
    public class GameContentData : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        public NotifiableCollection<ResourceData> ResourceDisplayCollection { get { return resourceItemDataDictionary.ValueCollection; } }

        private NotifiableDictionary<ResourceItem, ResourceData> resourceItemDataDictionary;
        private List<ResourceData> originalResourceCollection;

        public GameContentData()
        {
            resourceItemDataDictionary = new NotifiableDictionary<ResourceItem, ResourceData>();
        }

        public void Load()
        {
            GameItemManager.Instance.DynamicallyCreateGameItems = true;

            foreach (string resourceName in GameEngine.GetResourceItemList().Where(x => x != "obj").ToArray())
                AddNewResource(ResourceManager.Instance.LoadResource(resourceName));

            originalResourceCollection = new List<ResourceData>(resourceItemDataDictionary.ValueCollection);
        }

        public void TransferData()
        {
            CollectionDelta<ResourceData> collectionDelta = new CollectionDelta<ResourceData>(originalResourceCollection, resourceItemDataDictionary.ValueCollection);

            foreach (ResourceData newItem in collectionDelta.NewItems)
                ResourceTransfer.Add(newItem);

            foreach (ResourceData deletedItem in collectionDelta.DeletedItems)
                ResourceTransfer.Remove(deletedItem);

            foreach (ResourceData resourceData in ResourceDisplayCollection)
                resourceData.TransferDataReorder();

            foreach (ResourceData resourceData in ResourceDisplayCollection)
                resourceData.TransferDataUpdate();
        }


        public void SaveResourceItems()
        {
            DeleteOldResources();

            foreach (ResourceData animationResourceData in resourceItemDataDictionary.ValueCollection)
                animationResourceData.Save();

            ContentBuilder contentBuilder = new ContentBuilder(GameEngine.AnimationsDirectory);
            contentBuilder.Save();
            contentBuilder.Dispose();

            originalResourceCollection = new List<ResourceData>(resourceItemDataDictionary.ValueCollection);
        }

        private void DeleteOldResources()
        {
            CollectionDelta<ResourceData> collectionDelta = new CollectionDelta<ResourceData>(originalResourceCollection, resourceItemDataDictionary.ValueCollection);

            foreach (ResourceData deletedItem in collectionDelta.DeletedItems)
            {
                Directory.Delete(deletedItem.ResourceItem.ResourcePath, true);
                Directory.Delete(GameEngine.NodeLayoutDirectory + deletedItem.ResourceName, true);
            }
        }

        public ResourceData ObtainResourceData(ResourceItem resourceItem)
        {
            if (resourceItem == null)
                return null;

            if (!resourceItemDataDictionary.ContainsKey(resourceItem))
                return AddNewResource(resourceItem);
            else
                return resourceItemDataDictionary[resourceItem];
        }

        public void RemoveResource(ResourceData resourceItemData)
        {
            ResourceItem resourceItem = ResourceManager.Instance[resourceItemData.ResourceName];

            resourceItemDataDictionary.Remove(resourceItem);
            ResourceManager.Instance.RemoveResource(resourceItemData.ResourceName);

            ResourceTransfer.Remove(resourceItemData);
            resourceItem.Dispose();
        }

        public ResourceData AddNewResource()
        {
            ResourceItem resource = new ResourceItem(GameEngine.GetUniqueName(ResourceManager.Instance.ResourceCollection.Select(x => x.Name), "Resource"));
            ResourceManager.Instance.AddResourceItem(resource);

            ResourceData resourceItemData = AddNewResource(resource);

            ResourceTransfer.Add(resourceItemData);

            return resourceItemData;
        }

        public void UpdateCurrentPlayingNode(string resourceName, string scriptName, List<string> containerNodeNameList, string nodeName, bool isRunning)
        {
            NodeBaseWrapper nodeBaseWrapper = (NodeBaseWrapper)ObtainNodeFromList(containerNodeNameList, resourceName, scriptName).GetNode(nodeName);
            
            if (nodeBaseWrapper != null)
                nodeBaseWrapper.IsNodeCurrentlyPlaying = isRunning;
        }

        private ContainerNodeWrapper ObtainNodeFromList(List<string> containerNodeNameList, string resourceName, string scriptName)
        {
            ContainerNodeWrapper containerNodeWrapper = ResourceDisplayCollection
                .First(x => x.ResourceName == resourceName)
                .NodeScriptWrapperCollection.First(x => x.Name == scriptName)
                .RootContainerNodeWrapper;

            for (int i = 1; i < containerNodeNameList.Count; i++)//Skips the Root Container
            {
                NodeBaseWrapper nodeBaseWrapper = (NodeBaseWrapper)containerNodeWrapper.GetNode(containerNodeNameList[i]);
                if (nodeBaseWrapper is ContainerNodeWrapper)
                    containerNodeWrapper = (ContainerNodeWrapper)nodeBaseWrapper;
            }

            return containerNodeWrapper;
        }

        private ResourceData AddNewResource(ResourceItem resourceItem)
        {
            ResourceData resourceItemData = new ResourceData(resourceItem.Name);
            resourceItemDataDictionary.Add(resourceItem, resourceItemData);

            return resourceItemData;
        }

        private void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}
